﻿// The Nova Project by Ken Beckett.
// Copyright (C) 2007-2012 Inevitable Software, all rights reserved.
// Released under the Common Development and Distribution License, CDDL-1.0: http://opensource.org/licenses/cddl1.php

using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

using Nova.CodeDOM;

namespace Nova.UI
{
    /// <summary>
    /// The view model for a <see cref="CodeDOM.Operator"/>.
    /// </summary>
    public abstract class OperatorVM : ExpressionVM
    {
        #region /* CONSTRUCTORS */

        static OperatorVM()
        {
            InitializeCommands();
        }

        /// <summary>
        /// Create a view model instance for the specified <see cref="CodeDOM.Operator"/>.
        /// </summary>
        protected OperatorVM(Operator @operator, Dictionary<CodeObject, CodeObjectVM> dictionary)
            : base(@operator, dictionary)
        { }

        #endregion

        #region /* PROPERTIES */

        /// <summary>
        /// The underlying <see cref="CodeDOM.Operator"/> model.
        /// </summary>
        public Operator Operator
        {
            get { return (Operator)CodeObject; }
        }

        #endregion

        #region /* RENDERING */

        /// <summary>
        /// Determines if alternative symbols should be used to render operators.
        /// </summary>
        public static bool UseAlternativeDisplay;

        /// <summary>
        /// The <see cref="FontFamily"/> used to render symbols.
        /// </summary>
        public static FontFamily SymbolFont = new FontFamily("Symbol");

        /// <summary>
        /// Get the brush used to render the operator.
        /// </summary>
        protected virtual Brush RenderBrush(RenderFlags flags)
        {
            // This can be overloaded with an ERROR_BRUSH in the case that multiple complete-match
            // operator overloads are found for the operator (non-complete matches aren't errors,
            // and are ignored).  Also, some operators overload this with KEYWORD_BRUSH.
            return OPERATOR_BRUSH;
        }

        /// <summary>
        /// Render operator.
        /// </summary>
        protected virtual void RenderOperator(CodeRenderer renderer, RenderFlags flags)
        {
            renderer.RenderText(Operator.Symbol, RenderBrush(flags), this);
        }

        /// <summary>
        /// Alternate rendering of operator.
        /// </summary>
        protected virtual void AltRenderOperator(CodeRenderer renderer, RenderFlags flags)
        {
            RenderOperator(renderer, flags);  // Use normal rendering by default
        }

        #endregion

        #region /* COMMANDS */

        public static readonly RoutedCommand AlternativeDisplayCommand = new RoutedCommand("Alternative Operator Display", typeof(OperatorVM));

        private static void InitializeCommands()
        {
            AlternativeDisplayCommand.InputGestures.Add(new KeyGesture(Key.O, ModifierKeys.Alt));
        }

        public static new void BindCommands(Window window)
        {
            WPFUtil.AddCommandBinding(window, AlternativeDisplayCommand, alternativeDisplay_Executed);
        }

        private static void alternativeDisplay_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            UseAlternativeDisplay = !UseAlternativeDisplay;
            CodeRenderer.ReRenderAll();
        }

        #endregion
    }
}
